#ifndef ASAN_ALLOCTOR_H
#define ASAN_ALLOCTOR_H
#include "asan_internal_defs.h"
#include "asan_shadow_memory.h"
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_mapping.h"
#include "asan_avltree.h"


namespace __sanitizer {


class AsanChunkTree {
public:
  AsanChunk* root;
  uptr redzone_weak_min_size;
  uptr redzone_weak_max_size;
  inline void OnInit() {root = nullptr;}
  AsanChunkTree();
  void ClearAllChunks();
  ~AsanChunkTree();
  AsanChunk* FindChunkWithBeg(AsanChunk* N, uptr beg) const;
  AsanChunk* FindChunkContainsAddr(AsanChunk* N, uptr addr) const;
  AsanChunk* GetListLeftAsanChunk(const AsanChunk* chunk) const;
  AsanChunk* GetListRightAsanChunk(const AsanChunk* chunk) const;

  void InsertChunk(AsanChunk* chunk);
  void DeleteChunk(AsanChunk* chunk);
  AsanChunk* CreateLeftRedzoneChunk(const AsanChunk* chunk);
  AsanChunk* CreateRightRedzoneChunk(const AsanChunk* chunk);
  void UpdateChunkListInfo(AsanChunk* chunk);

  void PrintTree() const;
  void PrintList() const;
};

struct Allocator {
  int OnInit(AsanShadowMem *ptr);
  int OnDelete();
  int DoMalloc(void* addr, uptr size);
  int DoAlloca(void* addr, uptr size);
  int DoFree(void* addr);
  int DoQuickFree(AsanChunk* addr);

  inline AsanChunk* FindChunkWithBeg(void* beg) {
    return tree.FindChunkWithBeg(tree.root, (uptr)beg);
  }

  inline void DeleteChunk(AsanChunk* chunk) {
    tree.DeleteChunk(chunk);
  }

  AsanChunkTree tree;
  AsanShadowMem *shadow;
  uptr redzone_weak_min_size;
};

extern Allocator* allocatorPtr;

} // namespace __sanitizer


#endif // ASAN_ALLOCTOR_H